12.2 Coding Functions
Although it wasn't
made
very formal, we've already been using functions in
earlier chapters. For instance, to make a file object, we call the
built-in open function. Similarly, we use the
len built-in function to ask for the number of
items in a collection object.
In this chapter, we will learn how to write new
functions in Python. Functions we write behave the same way as the
built-ins already seen: they are called in expressions, are passed
values, and return results. But writing new functions requires a few
additional ideas that haven't yet been applied.
Moreover, functions behave very differently in Python than they do in
compiled languages like C. Here is a brief introduction to the main
concepts behind Python functions, which we will study in this
chapter:
def is executable code. Python functions are written with a new statement, the
def. Unlike functions in compiled languages such
as C, def is an executable statement—your
function does not exist until Python reaches and runs the
def. In fact, it's legal (and
even occasionally useful) to nest def statements
inside if, loops, and even other
defs. In typical operation, def
statements are coded in module files, and are naturally run to
generate functions when the module file is first imported. def creates an object and assigns it to a name. When Python reaches and runs a def statement, it
generates a new function object and assigns it to the
function's name. As with all assignments, the
function name becomes a reference to the function object.
There's nothing magic about the name of a
function—as we'll see, the function object can
be assigned to other names, stored in a list, and so on. Functions
may also be created with the lambda
expression—a more advanced concept deferred until later in this
chapter. return sends a result object back to the caller. When a function is called, the caller stops until the function
finishes its work and returns control to the caller. Functions that
compute a value send it back to the caller with
a return statement;
the returned value becomes the result of the function call. Functions
known as generators may also use the yield
statement to send a value back and suspend their state, such that
they may be resumed later; this is also an advanced topic covered
later in this chapter. Arguments are passed by assignment (object reference). In Python, arguments are passed to
functions by assignment (which, as
we've learned, means object reference). As
we'll see, this isn't quite like
C's passing rules or C++'s
reference parameters—the caller and function share objects by
references, but there is no name aliasing. Changing an argument name
does not also change a name in the caller, but changing passed-in
mutable objects can change objects shared by the caller. global declares module-level variables that
are to be assigned. By default, all names assigned in a function are local to that
function and exist only while the function runs. To assign a name in
the enclosing module, functions need to list it in a
global statement.
More generally, names are always looked up in
scopes—places where variables are
stored—and assignments bind names to scopes. Arguments, return values, and variables are not declared. As with everything in Python, there are no
type
constraints on functions. In fact, nothing about a function needs to
be declared ahead of time: we can pass in arguments of any type,
return any kind of object, and so on. As one consequence, a single
function can often be applied to a variety of object types.
If some of the preceding words didn't sink in,
don't worry—we'll explore all
these concepts with real code in this chapter. Let's
get started by expanding on these ideas, and looking at a few first
examples along the way.
12.2.1 def Statements
The def statement
creates a
function
object and assigns it to a name. Its general format is as follows:
def <name>(arg1, arg2,... argN):
<statements>
As with all compound Python statements, def
consists of a header line, followed by a block of statements, usually
indented (or a simple statement after the colon). The statement block
becomes the function's
body—the code Python executes each time
the function is called. The header line specifies a function
name that is assigned the function object, along
with a list of zero or more
arguments
(sometimes called parameters) in parenthesis. The
argument names in the header will be assigned to the objects passed
in parentheses at the point of call.
Function bodies often contain a return statement:
def <name>(arg1, arg2,... argN):
...
return <value>
The Python return statement can show up anywhere
in a function body; it ends the function call and sends a result back
to the caller. It consists of an object expression that gives the
function's result. The return is
optional; if it's not present, a function exits when
control flow falls off the end of the function body. Technically, a
function without a return returns the
None object automatically, but it is usually
ignored.
12.2.2 def Executes at Runtime
The Python def is a true executable statement:
when it runs, it creates and assigns a new function object to a
name.
Because
it's a statement, it can appear anywhere a statement
can—even nested in other statements. For instance,
it's completely legal to nest a function
def inside an if statement, to
select between alternative definitions:
if test:
def func( ): # Define func this way.
...
else:
def func( ): # Or else this way instead.
...
...
func( ) # Call the version selected and built.
One way to understand this code is to realize that the
def is much like an =
statement: it simply assigns a name at runtime. Unlike compiled
languages like C, Python functions do not need to be fully defined
before the program runs. More generally, defs are
not evaluated until reached and run, and code
inside defs is not evaluated
until the function is later called.
Because function definition happens at runtime,
there's nothing special about the function name,
only the object it refers to:
othername = func # Assign function object.
othername( ) # Call func again.
Here, the function was assigned to a different name, and called
through the new name. Like everything else in Python, functions are
just objects; they are recorded explicitly in memory at program
execution time.
|